package javango.forms.fields;

import java.lang.annotation.Annotation;
import java.util.Map;

import javango.forms.ValidationException;
import javango.forms.widgets.Widget;

public interface Field<T> {
	
	/**
	 * Cleans the value provided into the correct data type.
	 * @param value
	 * @param errors
	 * @return
	 * @throws ValidationException
	 */
	T clean(String value, Map<String, String> errors) throws ValidationException;
	
	/**
	 * Cleans the first value of the array into a value of the correct datatype.  
	 * Same as clean(value[0], errors) but also check for null or empty array and calls clean("", errors)
	 * @param value
	 * @param errors
	 * @return
	 * @throws ValidationException
	 */
	T clean(String[] value, Map<String, String> errors) throws ValidationException;
	
	/**
	 * Cleans the value array into an array of the correct data type.
	 * @param value
	 * @param errors
	 * @return
	 * @throws ValidationException
	 */
	T[] cleanAll(String[] value, Map<String, String> errors) throws ValidationException;
	
	/**
	 * Return a cleaned up version of the initial value for this field.  
	 * If the value passed in is null the field should use its initial property. TODO reword this
	 * This is mainly here to support modelchoicefield and may not stay around. DDN
	 * 
	 * @param value
	 * @return
	 */
	Object cleanInitialValue(Object value);
	
	Field<T> setName(String name);
	String getName();

	Widget getWidget();
	Field<T> setWidget(Widget widget);	
	Field<T> setWidget(Class<? extends Widget> widgetClass);
	Field<T> setWidget(Class<? extends Widget> widgetClass, String... widgetAttrs);
	Class<? extends Widget> getWidgetClass();
	
	Field<T> setWidgetAttrs(Map<String, String> attrs);
	Map<String, String> getWidgetAttrs();
	
	Widget getHiddenWidget();
	Field<T> setHiddenWidget(Widget hiddenWidget);
	Field<T> setHiddenWidget(Class<? extends Widget> widgetClass);
	Class<? extends Widget> getHiddenWidgetClass();
	
	boolean isRequired();
	Field<T> setRequired(boolean required);

	Object getInitial();
	Field<T> setInitial(Object initial);

	/**
	 * @Deprecated Use getLabel instead		
	 * @return
	 */
	String getVerboseName();
	/**
	 * @Deprecated Use setLabel instead
	 * @param verboseName
	 * @return
	 */
	Field<T> setVerboseName(String verboseName);
	
	String getLabel();
	Field<T> setLabel(String label);
	
	String getHelpText();
	Field<T> setHelpText(String helpText);	
		
	boolean isHidden();
	Field<T> setHidden(boolean hidden);

	boolean isEditable();
	Field<T> setEditable(boolean editable);

	boolean isAllowNull();
	Field<T> setAllowNull(boolean allowNull);
	
	void handleAnnotation(Annotation annotation);	
}
